﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using EmaMetadata;
using System.Media;

namespace EmaEditor
{
    public partial class frmProduct : Form
    {
        protected EmaBatch _batch;
        protected EmaProduct _product;
        protected EmaProduct _original_product_reference;
        protected frmMain _editor;
        protected bool _any_added = false;
        protected int _add_count = 0;

        #region Form Setup
        public EmaProduct Product
        {
            get { return _product; }
        }

        public frmProduct(EmaBatch batch, EmaProduct product, frmMain editor)
        {
            InitializeComponent();

            _batch = batch;
            _editor = editor;
            _original_product_reference = product;

            // This roundabout bit of code duplicates a product exactly.  This means that we can edit the _product object as much as we want without affecting the original object in the batch.
            // If the user hits cancel, no changes are made!
            if (_original_product_reference != null)
            {
                _product = Factory.StringToProduct(Factory.ProductToString(_original_product_reference));
            }
        }

        private void frmProduct_Load(object sender, EventArgs e)
        {
            // Setup the lists
            ddlGenre.SetupList(Factory.TABLE_COREGENRES);
            ddlPlatform.SetupList(Factory.TABLE_PLATFORMS);
            ddlPrimaryProductLine.SetupList(Factory.TABLE_PRIMARYPRODUCTLINE);
            ddlEditionType.SetupList(Factory.TABLE_EDITIONTYPES);
            ddlVendor.SetupList(Factory.TABLE_DIGITALSTOREFRONTS);
            ddlDownloadSize.SetupList(Factory.TABLE_DIGITALSIZEMEASUREMENTTYPES);
            ddlIdentifierType.SetupList(Factory.TABLE_IDENTIFIERTYPES);
            ddlTitleType.SetupList(Factory.TABLE_TITLETYPES);
            ddlDescriptionType.SetupList(Factory.TABLE_DESCRIPTIONTYPES);
            ddlGameplayType.SetupList(Factory.TABLE_MULTIPLAYERTYPES);
            ddlPriceType.SetupList(Factory.TABLE_PRICINGTYPES);
            ddlRatingsAgency.SetupList(Factory.TABLE_RATINGSAGENCIES);

            // Load the codes
            ddlPriceCountry.SetupList(Factory.ISOCountries);
            ddlReleaseDateCountry.SetupList(Factory.ISOCountries);
            ddlCurrency.SetupList(Factory.ISOCurrencies);

            // Load the object
            LoadFromObject();

            // Reset tab stop to false on all the link labels
            linkLabel1.TabStop = false;
            linkLabel2.TabStop = false;
            linkLabel3.TabStop = false;
            linkLabel4.TabStop = false;
            linkLabel5.TabStop = false;
            linkLabel6.TabStop = false;
            linkLabel7.TabStop = false;
            linkLabel8.TabStop = false;
            linkLabel9.TabStop = false;
            linkLabel10.TabStop = false;
            linkLabel11.TabStop = false;
            linkLabel12.TabStop = false;
            linkLabel13.TabStop = false;

            // Jump to the first field
            txtCompleteTitle.Focus();
            webBrowser1.Url = new Uri("https://code.google.com/p/ema-metadata/wiki/ContentDescriptors");
        }

        private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
        {
            epDetails.Clear();
        }
        #endregion

        #region Binding
        private void SaveToObject()
        {
            // Save Text to Object 
            Product.Extra = txtExtra.Text;

            // Save various titles 
            Product.SetTitle(Factory.ENTMERCH_NAMESPACE, "Complete", Factory.TITLE_COMPLETE_ID, txtCompleteTitle.Text);
            Product.SetTitle(Factory.ENTMERCH_NAMESPACE, "Medium", Factory.TITLE_MEDIUM_ID, txtMediumTitle.Text);
            Product.SetTitle(Factory.ENTMERCH_NAMESPACE, "Brief", Factory.TITLE_BRIEF_ID, txtBriefTitle.Text);
            Product.SetTitle(Factory.ENTMERCH_NAMESPACE, "Sorting", Factory.TITLE_SORTING_ID, txtSortingTitle.Text);

            // Store primary publisher and developer names
            Product.PrimaryDeveloper = txtPrimaryDeveloper.Text;
            Product.PrimaryPublisher = txtPrimaryPublisher.Text;

            // Save the dropdowns
            Product.Platform = ddlPlatform.GetFact();
            Product.PrimaryProductLine = ddlPrimaryProductLine.GetFact();
            Product.EditionType = ddlEditionType.GetFact();
            Product.Genre = ddlGenre.GetFact();

            // Save the characteristics
            if (Product.Characteristics == null)
            {
                Product.Characteristics = new EmaCharacteristics();
            }
            Product.Characteristics.VendorData = ddlVendor.GetFact();
            Product.Characteristics.DownloadSizeData = ddlDownloadSize.GetFact();
            //Decimal.TryParse(numDownloadSize.Value, out Product.Characteristics.Size);
            Product.Characteristics.Size = numDownloadSize.Value;
            // Save the players data
            int.TryParse(txtOverallPlayerMin.Text.Trim(), out Product.MinPlayers);
            int.TryParse(txtOverallPlayerMax.Text.Trim(), out Product.MaxPlayers);

            // Description
            Product.SetDescription(Factory.ENTMERCH_NAMESPACE, "Long", Factory.DESC_LONG_ID, txtLongDescription.Text);
        }

        private void LoadFromObject()
        {
            // Load all the various data tables
            RebindIdentities();
            RebindTitles();
            RebindDescriptions();
            RebindRatings();
            RebindGameplay();
            RebindRegions();
            RebindPrices();

            // Load Text From Object
            txtExtra.Text = Product.Extra;
            EmaTitle t = _product.GetTitle(Factory.ENTMERCH_NAMESPACE, "Complete");
            txtCompleteTitle.Text = t == null ? "" : t.Value;
            t = _product.GetTitle(Factory.ENTMERCH_NAMESPACE, "Medium");
            txtMediumTitle.Text = t == null ? "" : t.Value;
            t = _product.GetTitle(Factory.ENTMERCH_NAMESPACE, "Brief");
            txtBriefTitle.Text = t == null ? "" : t.Value;
            t = _product.GetTitle(Factory.ENTMERCH_NAMESPACE, "Sorting");
            txtSortingTitle.Text = t == null ? "" : t.Value;
            EmaDescription d = _product.GetDescription(Factory.ENTMERCH_NAMESPACE, "Long");
            txtLongDescription.Text = d == null ? "" : d.Value;
            txtPrimaryDeveloper.Text = _product.PrimaryDeveloper;
            txtPrimaryPublisher.Text = _product.PrimaryPublisher;

            // Load Players from Object
            txtOverallPlayerMin.Text = Product.MinPlayers.ToString();
            txtOverallPlayerMax.Text = Product.MaxPlayers.ToString();

            // Load the dropdowns
            ddlPlatform.SetFact(Product.Platform);
            ddlPrimaryProductLine.SetFact(Product.PrimaryProductLine);
            ddlEditionType.SetFact(Product.EditionType);
            ddlGenre.SetFact(Product.Genre);

            // Load the Characteristics
            if (Product.Characteristics != null)
            {
                ddlVendor.SetFact(Product.Characteristics.VendorData);
                ddlDownloadSize.SetFact(Product.Characteristics.DownloadSizeData);
                numDownloadSize.Value = _product.Characteristics.Size;
            }
        }

        private void RebindPrices()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Namespace");
            dt.Columns.Add("ID");
            dt.Columns.Add("Country");
            dt.Columns.Add("Currency");
            dt.Columns.Add("Price");
            dt.Columns.Add("EffectiveDate");
            foreach (EmaPrice p in _product.Pricing)
            {
                dt.Rows.Add(new object[] { p.PriceData.NS, p.PriceData.ID, p.CountryCode, p.Currency, p.Value.ToString(), p.EffectiveDate == null ? "N/A" : p.EffectiveDate.Value.ToString("yyyy-MM-dd") });
            }
            grdPrices.DataSource = dt;
        }

        private void RebindRegions()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Country");
            dt.Columns.Add("ReleaseDate");
            foreach (EmaRegion r in _product.Regions)
            {
                dt.Rows.Add(new object[] { r.CountryCode, r.ReleaseDate == null ? "" : r.ReleaseDate.Value.ToString("yyyy-MM-dd") });
            }
            grdReleaseDates.DataSource = dt;
        }

        private void RebindGameplay()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Namespace");
            dt.Columns.Add("ID");
            dt.Columns.Add("Type");
            dt.Columns.Add("Min");
            dt.Columns.Add("Max");
            foreach (EmaGameplay g in _product.Players)
            {
                dt.Rows.Add(new object[] { g.GameplayData.NS, g.GameplayData.ID, g.GameplayData.FactName, g.Min, g.Max });
            }
            grdGameplay.DataSource = dt;
            epDetails.Clear();
        }

        private void RebindDescriptions()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Namespace");
            dt.Columns.Add("ID");
            dt.Columns.Add("Type");
            dt.Columns.Add("Text");
            foreach (EmaDescription d in _product.Descriptions)
            {
                dt.Rows.Add(new object[] { d.DescriptionData.NS, d.DescriptionData.ID, d.DescriptionData.FactName, d.Value });
            }
            grdDescriptions.DataSource = dt;
        }

        private void RebindRatings()
        {
            DataTable ratings = new DataTable();
            ratings.Columns.Add("Namespace");
            ratings.Columns.Add("ID");
            ratings.Columns.Add("Agency");
            ratings.Columns.Add("Certificate");
            ratings.Columns.Add("Rating");
            foreach (EmaRating r in _product.Ratings)
            {
                ratings.Rows.Add(new object[] { r.AgencyData.NS, r.AgencyData.ID, r.AgencyData.FactName, r.Certificate, r.Rating });
            }
            grdRatings.DataSource = ratings;
        }

        private void RebindTitles()
        {
            DataTable texts = new DataTable();
            texts.Columns.Add("Namespace");
            texts.Columns.Add("ID");
            texts.Columns.Add("Name");
            texts.Columns.Add("Value");
            foreach (EmaTitle title in _product.Titles)
            {
                texts.Rows.Add(new object[] { title.TitleData.NS, title.TitleData.ID, title.TitleData.FactName, title.Value });
            }
            grdTitles.DataSource = texts;
        }

        private void RebindIdentities()
        {
            DataTable identities = new DataTable();
            identities.Columns.Add("Namespace");
            identities.Columns.Add("ID");
            identities.Columns.Add("Name");
            identities.Columns.Add("Value");
            foreach (EmaIdentity id in _product.Identities)
            {
                identities.Rows.Add(new object[] { id.IdentityData.NS, id.IdentityData.ID, id.IdentityData.FactName, id.Value });
            }
            grdIdentities.DataSource = identities;
        }
        #endregion

        #region Save / Add / Cancel buttons
        private void btnSave_Click(object sender, EventArgs e)
        {
            //// Save the values to the product
            //if (!Validate()) {
            //    return;
            //}

            if (generalTabIsValid() == false) return;
            SaveToObject();

            // Okay, now we have to port the object back to the batch
            int pos = _batch.Products.IndexOf(_original_product_reference);
            if (pos >= 0)
            {
                _batch.Products.RemoveAt(pos);
                _batch.Products.Insert(pos, _product);
            }
            else
            {
                _batch.Products.Add(_product);
            }

            if (debug == true)
            { // Used to ensure each "DEBUGX" product has a unique number at the end   ~F
                debugCounter++;
            }

            // Wrap up this form
            DialogResult = System.Windows.Forms.DialogResult.OK;
            Close();
        }

        private void btnSaveAdd_Click(object sender, EventArgs e)
        {

            if (generalTabIsValid() == false) return;
            SaveToObject();

            // Now we port this object back to the batch
            int pos = _batch.Products.IndexOf(_original_product_reference);
            if (pos >= 0)
            {
                _batch.Products.RemoveAt(pos);
                _batch.Products.Insert(pos, _product);
            }
            else
            {
                _batch.Products.Add(_product);
            }
            _any_added = true;
            _editor.Rebind();
            _editor.SetDirty(true);

            // Reset our status and continue working
            _original_product_reference = null;
            _product = new EmaProduct();
            LoadFromObject();

            // If this product has been made for debugging purposes, take record of that   ~F
            if (debug == true)
            {
                debugCounter++;
            }
            debug = false; // resets it. doesn't need to occur for btnSave since product window closes on save  ~F

            // Let the user know what happened
            _add_count++;
            lblSaveAdd.Text = String.Format("{0} product(s) added.", _add_count);
        }



        private void btnCancel_Click(object sender, EventArgs e)
        {
            // Remind the user that cancelling loses their changes
            if (MessageBox.Show("Do you wish to cancel and lose all changes?", "Confirm Cancel", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
            {

                // Wrap up this form - but if the user ever did a "save/add" return OK rather than cancel.
                if (_any_added)
                {
                    DialogResult = System.Windows.Forms.DialogResult.OK;
                }
                else
                {
                    DialogResult = System.Windows.Forms.DialogResult.Cancel;
                }
                Close();
            }
        }
        #endregion

        #region General Tab

        private bool generalTabIsValid() // basic validation for gen tab
        {

            CancelEventArgs e = new CancelEventArgs();
            epGeneral.Clear();

            txtCompleteTitle.EnsureFieldNotEmpty("Complete title required", e, epGeneral);
            txtPrimaryPublisher.EnsureFieldNotEmpty("Primary publisher required", e, epGeneral);
            txtPrimaryDeveloper.EnsureFieldNotEmpty("Primary developer required", e, epGeneral);
            txtLongDescription.EnsureFieldNotEmpty("Long description required", e, epGeneral);

            txtOverallPlayerMin.EnsureNumIsValid(e, epGeneral);
            txtOverallPlayerMax.EnsureNumIsValid(e, epGeneral);
            txtOverallPlayerMax.EnsureGreaterThan(txtOverallPlayerMin, e, epGeneral);

            ddlPlatform.EnsureDropListSelected(e, epGeneral);
            ddlGenre.EnsureDropListSelected(e, epGeneral);
            ddlEditionType.EnsureDropListSelected(e, epGeneral);
            ddlPrimaryProductLine.EnsureDropListSelected(e, epGeneral);
            bool valid = true;
            if (e.Cancel) valid = false;
            return valid;
        }

        #region Titlebox Autocopy Code

        #region Alternative
        //private void copyTextBoxContent(TextBox inbx, TextBox outbx)
        //{
        //    if (outbx.Text.Trim() == "" || outbx.Text.Trim() == inbx.Text.Trim())
        //    {
        //        outbx.Text = inbx.Text;
        //    }
        //}

        //private void txtCompleteTitle_Leave(object sender, EventArgs e)
        //{
        //    copyTextBoxContent(txtCompleteTitle, txtMediumTitle);
        //    copyTextBoxContent(txtCompleteTitle, txtBriefTitle);
        //    copyTextBoxContent(txtCompleteTitle, txtSortingTitle);
        //}
        #endregion
        /*I committed the following code not knowing you had already done something similiar with the code above^
         * However, the code below will know when to "sync" the boxes, so that way if the user decides to change the Complete Title, 
         * other fields will change too if they are the same:
         * I believe Ted's code only copied the Complete Title when it was first entered. 
         * ~F
         */
        bool medium;
        bool brief;
        bool sorting;

        private bool shouldSyncTextBoxes(TextBox inbx, TextBox outbx)
        {
            bool shouldupdate = false;
            if (outbx.Text.Trim() == "" || outbx.Text.Trim() == inbx.Text.Trim())
            {
                /*outbx.SelectionStart = 0;
                outbx.SelectionLength = outbx.Text.Length;*/
                shouldupdate = true;
            }
            return shouldupdate;
        }

        private void doSyncTextBoxes(TextBox inbx, TextBox outbx, bool shouldupdate)
        {
            if (shouldupdate == true)
            {
                outbx.Text = inbx.Text;
            }

        }


        private void txtCompleteTitle_EnterF(object sender, EventArgs e)
        {
            medium = shouldSyncTextBoxes(txtCompleteTitle, txtMediumTitle);
            brief = shouldSyncTextBoxes(txtCompleteTitle, txtBriefTitle);
            sorting = shouldSyncTextBoxes(txtCompleteTitle, txtSortingTitle);
            FormControl_Enter(sender, e);
        }


        private void txtCompleteTitle_LeaveF(object sender, EventArgs e)
        {
            txtTitleBoxes_Leave(sender, e);
            doSyncTextBoxes(txtCompleteTitle, txtMediumTitle, medium);
            doSyncTextBoxes(txtCompleteTitle, txtBriefTitle, brief);
            doSyncTextBoxes(txtCompleteTitle, txtSortingTitle, sorting);
        }


        #endregion

        #endregion

        #region Help Links
        private void linkLabel11_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://code.google.com/p/ema-metadata/wiki/PriceInformation");
        }

        private void linkLabel10_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://code.google.com/p/ema-metadata/wiki/ReleaseInformation");
        }

        private void linkLabel4_LinkClicked_1(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://code.google.com/p/ema-metadata/wiki/GameplayInformation");
        }

        private void linkLabel12_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://code.google.com/p/ema-metadata/wiki/GameplayInformation");
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://code.google.com/p/ema-metadata/wiki/ItemTitles");
        }

        private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://code.google.com/p/ema-metadata/wiki/BasicProductFacts");
        }

        private void linkLabel3_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://code.google.com/p/ema-metadata/wiki/ContentDescriptors");
        }

        private void linkLabel4_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://code.google.com/p/ema-metadata/wiki/MultiPlayerInformation");
        }

        private void linkLabel5_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://code.google.com/p/ema-metadata/wiki/SupplyChainCharacteristics");
        }

        private void linkLabel9_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://code.google.com/p/ema-metadata/wiki/ItemTitles");
        }

        private void linkLabel7_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://code.google.com/p/ema-metadata/wiki/ItemIdentification");
        }

        private void linkLabel6_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://code.google.com/p/ema-metadata/wiki/ContentDescriptors");
        }

        private void linkLabel8_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://code.google.com/p/ema-metadata/wiki/RatingInformation");
        }
        #endregion

        #region Identifier Tab
        // nothing wrong here ~F
        private void btnAddIdentifier_Click(object sender, EventArgs e)
        {
            // Are all the fields in a valid state?
            epDetails.Clear();
            CancelEventArgs c = new CancelEventArgs();
            ddlIdentifierType.EnsureDropListSelected(c, epDetails);
            txtIdentityValue.EnsureFieldNotEmpty(c, epDetails);
            if (c.Cancel)
            {
                SystemSounds.Beep.Play();
                return;
            }

            // Retrieve all the information we want
            EmaFact f = ddlIdentifierType.GetFact();
            _product.SetIdentity(f.NS, f.FactName, f.ID, txtIdentityValue.Text);

            // Reset identity section
            txtIdentityValue.Text = "";
            ddlIdentifierType.SelectedIndex = 0;
            RebindIdentities();
        }
        #endregion

        #region Characteristics Tab
        private void txtDownloadSize_KeyPress(object sender, KeyPressEventArgs e)
        {

        }
        #endregion

        #region Titles Tab
        private void btnTitleAdd_Click(object sender, EventArgs e)
        {
            // Are all the fields in a valid state?
            epDetails.Clear();
            CancelEventArgs c = new CancelEventArgs();
            ddlTitleType.EnsureDropListSelected(c, epDetails);
            txtTitle.EnsureFieldNotEmpty(c, epDetails);
            if (c.Cancel)
            {
                SystemSounds.Beep.Play();
                return;
            }

            // Retrieve all the information
            EmaFact f = ddlTitleType.GetFact();
            _product.SetTitle(f.NS, f.FactName, f.ID, txtTitle.Text);

            // Reset identity section
            txtTitle.Text = "";
            ddlTitleType.SelectedIndex = 0;
            RebindTitles();
        }



        #endregion

        #region Gameplay Tab
        private void btnGameplayAdd_Click(object sender, EventArgs e)
        {
            // Are all the fields in a valid state?
            epDetails.Clear();
            CancelEventArgs c = new CancelEventArgs();
            ddlGameplayType.EnsureDropListSelected(c, epDetails);
            txtGameplayMin.EnsureNumIsValid(c, epDetails);
            txtGameplayMax.EnsureNumIsValid(c, epDetails);
            txtGameplayMax.EnsureGreaterThan(txtGameplayMin, c, epDetails);
            if (c.Cancel)
            {
                SystemSounds.Beep.Play();
                return;
            }

            // Retrieve all the values
            EmaFact f = ddlGameplayType.GetFact();
            _product.SetGameplay(f.NS, f.FactName, f.ID, Convert.ToInt32(txtGameplayMin.Text), Convert.ToInt32(txtGameplayMax.Text)); // doesn't do anything anymore

            // Reset gameplay section
            txtGameplayMin.Text = "";
            txtGameplayMax.Text = "";
            ddlGameplayType.SelectedIndex = 0;
            RebindGameplay();
        }
        #endregion

        #region Description Tab
        private void btnDescriptionAdd_Click(object sender, EventArgs e)
        {
            // Are all the fields in a valid state?
            epDetails.Clear();
            CancelEventArgs c = new CancelEventArgs();
            ddlDescriptionType.EnsureDropListSelected(c, epDetails);
            txtDescription.EnsureFieldNotEmpty(c, epDetails);
            if (c.Cancel)
            {
                SystemSounds.Beep.Play();
                return;
            }

            // Retrieve all details
            EmaFact f = ddlDescriptionType.GetFact();
            _product.SetDescription(f.NS, f.FactName, f.ID, txtDescription.Text);

            // Reset description section
            txtDescription.Text = "";
            ddlDescriptionType.SelectedIndex = 0;
            RebindDescriptions();
        }
        #endregion

        #region Edit and Delete items out of a grid
        private DataGridView _selected_grid = null;

        private List<EmaFact> GetFactsFromSelectedGrid()
        {
            List<EmaFact> list = new List<EmaFact>();
            foreach (DataGridViewRow row in _selected_grid.SelectedRows)
            {
                list.Add(row.GetFact());
            }
            return list;
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Gameplay grid deletion
            if (_selected_grid == grdGameplay)
            {
                foreach (EmaFact f in GetFactsFromSelectedGrid())
                {
                    _product.RemoveGameplay(f.NS, f.ID);
                }
                RebindGameplay();
            }

            // Identity grid deletion    ~F
            if (_selected_grid == grdIdentities)
            {
                foreach (EmaFact f in GetFactsFromSelectedGrid())
                {
                    _product.RemoveIdentity(f.NS, f.ID);
                }
                RebindIdentities();
            }

            // Titles grid deletion ~F
            if (_selected_grid == grdTitles)
            {
                foreach (EmaFact f in GetFactsFromSelectedGrid())
                {
                    _product.RemoveTitle(f.NS, f.ID);
                }
                RebindTitles();
            }

            // "" Descriptions  ~F
            if (_selected_grid == grdDescriptions)
            {
                foreach (EmaFact f in GetFactsFromSelectedGrid())
                {
                    _product.RemoveDescription(f.NS, f.ID);
                }
                RebindDescriptions();
            }

            if (_selected_grid == grdPrices)
            {
                foreach (EmaFact f in GetFactsFromSelectedGrid())
                {

                    // Retrieve the other values needed from the grid
                    string countryCode = _selected_grid.SelectedRows[0].Cells["Country"].Value.ToString();
                    Nullable<DateTime> effectiveDate = null;
                    DateTime dt = DateTime.Now;
                    if (DateTime.TryParse(_selected_grid.SelectedRows[0].Cells["EffectiveDate"].Value.ToString(), out dt))
                    {
                        effectiveDate = dt;
                    }

                    _product.RemovePrice(f.NS, null, f.ID, countryCode, effectiveDate);
                }
                RebindPrices();
            }

            if (_selected_grid == grdRatings)
            {
                foreach (EmaFact f in GetFactsFromSelectedGrid())
                {
                    _product.RemoveRating(f.NS, f.ID);
                }
                RebindRatings();
            }

            if (_selected_grid == grdReleaseDates)
            {
                for (int i = 0; i < grdReleaseDates.SelectedRows.Count; i++)
                {
                    string code = grdReleaseDates.Rows[i].Cells["Country"].Value.ToString();
                    _product.RemoveRegions(code);
                }
                RebindRegions();
            }
        }

        private void editToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EmaFact f = GetFactsFromSelectedGrid().FirstOrDefault();


            /* As soon as user hits "edit" it compiles a list of all the emafacts inside of said grid
            But why FirstOrDefault? shouldn't it pick based on which specific row the user right clicks on? ~F
             */
            // Gameplay grid to editor
            if (_selected_grid == grdGameplay)
            {
                if (f == null) return;
                EmaGameplay g = _product.GetPlayers(f.NS, f.ID);
                txtGameplayMin.Text = g.Min.ToString();
                txtGameplayMax.Text = g.Max.ToString();
                ddlGameplayType.SetFact(f);

            }

            // Identity grid editing    ~F
            if (_selected_grid == grdIdentities)
            {
                if (f == null) return;
                EmaIdentity i = _product.GetIdentity(f.NS, f.ID);
                txtIdentityValue.Text = i.Value;
                ddlIdentifierType.SetFact(f);
            }

            // Titles 
            if (_selected_grid == grdTitles)
            {
                if (f == null) return;
                EmaTitle t = _product.GetTitle(f.NS, f.ID);
                txtTitle.Text = t.Value;
                ddlTitleType.SetFact(f);
            }

            // Descriptions 
            if (_selected_grid == grdDescriptions)
            {
                if (f == null) return;
                EmaDescription t = _product.GetDescription(f.NS, f.ID);
                txtDescription.Text = t.Value;
                ddlDescriptionType.SetFact(f);
            }


            // Ratings 
            if (_selected_grid == grdRatings)
            {
                if (f == null) return;
                EmaRating t = _product.GetRating(f.NS, f.ID);
                txtRating.Text = t.Rating;
                ddlRatingsAgency.SetFact(f);
                txtRatingCertificate.Text = t.Certificate;
            }


            // Prices
            if (_selected_grid == grdPrices)
            {
                if (f == null) return;
                // Retrieve the other values needed from the grid
                string countryCode = _selected_grid.SelectedRows[0].Cells["Country"].Value.ToString();
                string currency = _selected_grid.SelectedRows[0].Cells["Currency"].Value.ToString();
                Nullable<DateTime> effectiveDate = null;
                DateTime dt = DateTime.Now;
                if (DateTime.TryParse(_selected_grid.SelectedRows[0].Cells["EffectiveDate"].Value.ToString(), out dt))
                {
                    effectiveDate = dt;
                }

                EmaPrice t = _product.GetPrice(f.NS, f.FactName, f.ID, countryCode, effectiveDate);
                if (t != null)
                {
                    txtPrice.Text = t.Value.ToString();
                    ddlPriceType.SetFact(f);
                    ddlPriceCountry.SetCode(t.CountryCode);
                    ddlCurrency.SetCode(currency);

                    // Set the nullable date time correctly
                    if (t.EffectiveDate.HasValue)
                    {
                        dtpEffectiveDate.Checked = true;
                        dtpEffectiveDate.Value = (DateTime)t.EffectiveDate;
                    }
                    else
                    {
                        dtpEffectiveDate.Checked = false;
                    }
                }
            }

            //Regions/Release Date                 ~F
            if (_selected_grid == grdReleaseDates)
            {
                try
                {
                    EmaRegion t = _product.GetRegion(_selected_grid.SelectedRows[0].Cells["Country"].Value.ToString());
                    ddlReleaseDateCountry.SetCode(t.CountryCode);
                    dtpReleaseDate.Value = (DateTime)t.ReleaseDate;
                }
                catch
                {
                }
            }
        }

        private void grdContextMenu_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                _selected_grid = sender as DataGridView;

                // Check where the user clicked and activate that row
                var ht = _selected_grid.HitTest(e.X, e.Y);
                if (ht.RowIndex >= 0)
                {
                    for (int i = 0; i < _selected_grid.Rows.Count; i++)
                    {
                        _selected_grid.Rows[i].Selected = (i == ht.RowIndex);
                    }
                }

                // Show the context menu
                mnuGridContext.Show(_selected_grid, e.Location);
            }
        }
        #endregion

        #region Release Dates Section
        private void btnReleaseDateAdd_Click(object sender, EventArgs e)
        {
            // Are all the fields in a valid state?
            epDetails.Clear();
            CancelEventArgs c = new CancelEventArgs();
            ddlReleaseDateCountry.EnsureDropListSelected(c, epDetails);
            if (c.Cancel)
            {
                SystemSounds.Beep.Play();
                return;
            }

            // Retrieve the details
            if (_product.GetRegion(ddlReleaseDateCountry.SelectedValue.ToString()) == null)
            {
                EmaRegion r = new EmaRegion() { CountryCode = ddlReleaseDateCountry.SelectedValue.ToString(), ReleaseDate = dtpReleaseDate.Value };
                _product.Regions.Add(r);
            }
            else // If their is already a corresponding region release
            {
                _product.SetRegion(ddlReleaseDateCountry.SelectedValue.ToString(), dtpReleaseDate.Value);
            }

            RebindRegions();

            // Update user interface
            dtpReleaseDate.Value = DateTime.Now;
            ddlReleaseDateCountry.SelectedIndex = 0;
        }
        #endregion

        #region Pricing Section
        private void btnPriceAdd_Click(object sender, EventArgs e)
        {
            // Are all the fields in a valid state?
            epDetails.Clear();
            CancelEventArgs c = new CancelEventArgs();
            txtPrice.EnsureNumIsValid(typeof(Decimal), c, epDetails);
            ddlCurrency.EnsureDropListSelected(c, epDetails);
            ddlPriceType.EnsureDropListSelected(c, epDetails);
            ddlPriceCountry.EnsureDropListSelected(c, epDetails);
            if (c.Cancel)
            {
                SystemSounds.Beep.Play();
                return;
            }

            // Did all the stuff pass?
            Decimal price = Decimal.Parse(txtPrice.Text);
            EmaFact f = ddlPriceType.GetFact();
            Nullable<DateTime> dt = null;
            if (dtpEffectiveDate.Checked)
            {
                dt = dtpEffectiveDate.Value;
            }
            _product.SetPrice(f.NS, f.FactName, f.ID, ddlPriceCountry.SelectedValue.ToString(), ddlCurrency.SelectedValue.ToString(), price, dt);
            RebindPrices();

            // Clear out the controls
            ddlPriceCountry.SelectedIndex = 0;
            ddlCurrency.SelectedIndex = 0;
            ddlPriceType.SelectedIndex = 0;
            txtPrice.Text = "";
            dtpEffectiveDate.Value = DateTime.Now;
            dtpEffectiveDate.Checked = false;
        }
        #endregion

        #region Ratings Section
        private void btnAddRating_Click(object sender, EventArgs e)
        {
            // Are all the fields in a valid state?
            epDetails.Clear();
            CancelEventArgs c = new CancelEventArgs();
            ddlRatingsAgency.EnsureDropListSelected(c, epDetails);
            txtRating.EnsureFieldNotEmpty(c, epDetails);
            if (c.Cancel)
            {
                SystemSounds.Beep.Play();
                return;
            }


            // Retrieve all the data
            EmaFact agency = ddlRatingsAgency.GetFact();
            EmaRating r = new EmaRating() { AgencyData = agency, Certificate = txtRatingCertificate.Text, Rating = txtRating.Text };
            _product.Ratings.Add(r);

            // Update the user interface
            RebindRatings();
            txtRating.Text = "";
            txtRatingCertificate.Text = "";
            ddlRatingsAgency.SelectedIndex = 0;
        }
        #endregion

        #region Easy Debug Code


        public static int debugCounter = 1;
        bool debug = false;
        private void frmProduct_KeyDownDebug(object sender, KeyEventArgs e)
        {
            if (e.KeyData == (Keys.Control | Keys.D | Keys.Shift))
            {
                txtCompleteTitle.Text = "DEBUG" + debugCounter;
                ddlPlatform.SelectedIndex = 1;
                ddlGenre.SelectedIndex = 1;
                ddlEditionType.SelectedIndex = 1;
                ddlPrimaryProductLine.SelectedIndex = 1;
                txtPrimaryPublisher.Text = "DEBUG";
                txtPrimaryDeveloper.Text = "DEBUG";
                txtLongDescription.Text = "DEBUG";
                debug = true;
            }
        }
        #endregion

        #region Help stuff
        private void btnHelp_Click(object sender, EventArgs e)
        {
            splitContainer1.Panel2Collapsed = !splitContainer1.Panel2Collapsed;
        }

        private void FormControl_Enter(object sender, EventArgs e)
        {
            Control c = sender as Control;
            if (c != null)
            {
                string help_tag = c.Tag as string;
                if (!String.IsNullOrEmpty(help_tag))
                {
                    if (!splitContainer1.Panel2Collapsed)
                    {
                        webBrowser1.Url = new Uri(help_tag);
                    }
                }
            }
        }
        #endregion

        private void txtLongDescription_Leave(object sender, EventArgs e)
        {
            CancelEventArgs c = new CancelEventArgs();
            txtLongDescription.EnsureFieldNotEmpty("Long description required", c, epGeneral, false);
            if (c.Cancel) return;
            Product.SetDescription(Factory.ENTMERCH_NAMESPACE, "Long", Factory.DESC_LONG_ID, txtLongDescription.Text);
            RebindDescriptions();
        }

        private void tabControl1_Selected(object sender, TabControlEventArgs e)
        {
            //helpURLOnTab(e);
            FormControl_Enter(tabControl1.SelectedTab, e);
           

            titleGridToTxtBox(Factory.TITLE_COMPLETE_ID, txtCompleteTitle);
            titleGridToTxtBox(Factory.TITLE_MEDIUM_ID, txtMediumTitle);
            titleGridToTxtBox(Factory.TITLE_BRIEF_ID, txtBriefTitle);
            titleGridToTxtBox(Factory.TITLE_SORTING_ID, txtSortingTitle);

            titleTxtBoxToGrid("Complete", Factory.TITLE_COMPLETE_ID, txtCompleteTitle, "Complete title required");
            titleTxtBoxToGrid("Medium", Factory.TITLE_MEDIUM_ID, txtMediumTitle, "Medium title required");
            titleTxtBoxToGrid("Brief", Factory.TITLE_BRIEF_ID, txtBriefTitle, "Brief title required");
            titleTxtBoxToGrid("Sorting", Factory.TITLE_SORTING_ID, txtSortingTitle, "Sorting title required");

            EmaDescription d = _product.GetDescription(Factory.ENTMERCH_NAMESPACE, Factory.DESC_LONG_ID);
            if (d != null)
            {
                txtLongDescription.Text = d.Value;
            }

        }

        private void txtTitleBoxes_Leave(object sender, EventArgs e)
        {
            if (sender == txtCompleteTitle)
            {
                titleTxtBoxToGrid("Complete", Factory.TITLE_COMPLETE_ID, txtCompleteTitle, "Complete title required");
            }
            else if (sender == txtMediumTitle)
            {
                titleTxtBoxToGrid("Medium", Factory.TITLE_MEDIUM_ID, txtMediumTitle, "Medium title required");
            }
            else if (sender == txtBriefTitle)
            {
                titleTxtBoxToGrid("Brief", Factory.TITLE_BRIEF_ID, txtBriefTitle, "Brief title required");
            }
            else if (sender == txtSortingTitle)
            {
                titleTxtBoxToGrid("Sorting", Factory.TITLE_SORTING_ID, txtSortingTitle, "Sorting title required");
            }

        }

        private void titleTxtBoxToGrid(string FactName, int id, TextBox txtbox, string errorname)
        {
            CancelEventArgs c = new CancelEventArgs();
            txtbox.EnsureFieldNotEmpty(errorname, c, epGeneral, false);
            if (c.Cancel) return;
            Product.SetTitle(Factory.ENTMERCH_NAMESPACE, FactName, id, txtbox.Text);
            RebindTitles();
        }

        private void titleGridToTxtBox(int id, TextBox txtbox)
        {
            EmaTitle t = _product.GetTitle(Factory.ENTMERCH_NAMESPACE, id);
            if (t != null)
            {
                txtbox.Text = t.Value.ToString();
            }

        }



        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {

        }



        //string help_tag = c.Tag as string;
        //        if (!String.IsNullOrEmpty(help_tag)) {
        //            if (!splitContainer1.Panel2Collapsed) {
        //                webBrowser1.Url = new Uri(help_tag);
        //            }


        private void tabControl1_TabIndexChanged(object sender, EventArgs e)
        {

        }

    }
}

